#!/usr/bin/env python3
"""
分析Go二进制文件的加密逻辑
"""

import subprocess
import re
import struct

def analyze_go_symbols():
    """分析Go符号表"""
    print("🔍 === 分析Go符号表 ===\n")
    
    # 使用go tool nm分析
    try:
        # 尝试使用objdump获取符号
        result = subprocess.run(['objdump', '-t', 'Lingma'], 
                              capture_output=True, text=True)
        
        if result.returncode == 0:
            # 搜索相关函数
            encrypt_funcs = []
            lines = result.stdout.strip().split('\n')
            
            keywords = ['encrypt', 'decode', 'encode', 'transform', 
                       'substitute', 'cipher', 'base64', 'map']
            
            for line in lines:
                lower_line = line.lower()
                for keyword in keywords:
                    if keyword in lower_line:
                        encrypt_funcs.append(line.strip())
                        break
            
            print(f"找到 {len(encrypt_funcs)} 个相关函数:")
            for func in encrypt_funcs[:20]:
                print(f"  {func}")
    except:
        print("无法运行objdump")
    
    # 使用strings查找Go函数名
    print("\n\n使用strings查找Go函数:")
    result = subprocess.run(['strings', 'Lingma'], 
                          capture_output=True, text=True)
    
    go_funcs = []
    for line in result.stdout.split('\n'):
        # Go函数通常包含包路径
        if '.' in line and '/' in line:
            lower_line = line.lower()
            if any(k in lower_line for k in ['encode', 'decode', 'encrypt', 'transform']):
                go_funcs.append(line)
    
    print(f"找到 {len(go_funcs)} 个相关Go函数:")
    for func in go_funcs[:15]:
        print(f"  {func}")

def search_custom_base64():
    """搜索自定义Base64实现"""
    print("\n\n🔤 === 搜索自定义Base64字符表 ===")
    
    # 我们的自定义字符集
    custom_charset = "!#%&()*,.@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_abcdefghijklmnopqrstuvwxyz"
    
    with open('Lingma', 'rb') as f:
        data = f.read()
    
    # 搜索字符集或其片段
    search_patterns = [
        custom_charset.encode(),
        custom_charset[:32].encode(),  # 前半部分
        custom_charset[32:].encode(),  # 后半部分
        b"!#%&()*,.",  # 特殊字符部分
        b"@ABCDEFGHIJKLMNOPQRSTUVWXYZ",  # 大写字母
        b"^_abcdefghijklmnopqrstuvwxyz"   # 小写字母
    ]
    
    for i, pattern in enumerate(search_patterns):
        pos = data.find(pattern)
        if pos != -1:
            print(f"\n找到模式 {i+1} 在偏移 0x{pos:08x}")
            print(f"模式: {pattern[:50]}")
            
            # 查看前后内容
            start = max(0, pos - 100)
            end = min(len(data), pos + len(pattern) + 100)
            context = data[start:end]
            
            # 保存上下文
            with open(f'base64_context_{i}.bin', 'wb') as f:
                f.write(context)
            
            print(f"已保存上下文到 base64_context_{i}.bin")

def analyze_byte_substitution():
    """分析字节替换逻辑"""
    print("\n\n🔀 === 分析字节替换逻辑 ===")
    
    # 基于已知映射推测算法
    known = {
        0xa1: ord('m'),  # 161 -> 109  差值: -52
        0xf3: ord('o'),  # 243 -> 111  差值: -132
        0x6b: ord('d'),  # 107 -> 100  差值: -7
        0x31: ord('e'),  # 49 -> 101   差值: +52
        0xb0: ord('l'),  # 176 -> 108  差值: -68
        0x69: ord('"'),  # 105 -> 34   差值: -71
        0x01: ord(':'),  # 1 -> 58     差值: +57
        0x90: ord(' ')   # 144 -> 32   差值: -112
    }
    
    print("分析映射规律:")
    for src, dst in sorted(known.items()):
        diff = dst - src
        print(f"  0x{src:02x} -> 0x{dst:02x} (差值: {diff:+4d})")
    
    # 查找可能的查找表
    print("\n搜索查找表模式...")
    
    with open('Lingma', 'rb') as f:
        data = f.read()
    
    # 方法1: 搜索连续的字节序列包含我们的映射值
    # 例如搜索包含 109(m), 111(o), 100(d), 101(e), 108(l) 的区域
    target_bytes = [109, 111, 100, 101, 108, 34, 58, 32]  # model": 
    
    # 查找包含多个目标字节的256字节区域
    for offset in range(len(data) - 256):
        segment = data[offset:offset+256]
        
        # 计算包含多少个目标字节
        contains = sum(1 for b in target_bytes if b in segment)
        
        if contains >= 6:
            print(f"\n在偏移 0x{offset:08x} 找到包含{contains}个目标字节的段")
            
            # 检查是否可能是映射表
            # 验证已知映射
            valid = True
            for src, dst in known.items():
                if segment[src] != dst:
                    valid = False
                    break
            
            if valid:
                print("✅ 这可能是正确的映射表!")
                with open('found_mapping_table.bin', 'wb') as f:
                    f.write(segment)
                return segment

def search_in_go_binary_format():
    """按Go二进制格式搜索"""
    print("\n\n📦 === Go二进制格式分析 ===")
    
    # Go的数据通常有对齐要求
    with open('Lingma', 'rb') as f:
        data = f.read()
    
    # 搜索可能的256字节数组
    # 在Go中，数组通常对齐到8字节边界
    print("搜索256字节对齐的数据块...")
    
    found_blocks = []
    
    for offset in range(0, len(data) - 256, 8):  # 8字节对齐
        block = data[offset:offset+256]
        
        # 检查是否像查找表
        # 1. 每个值应该在0-255范围内（废话）
        # 2. 应该包含大量不同的值
        unique_values = len(set(block))
        
        # 3. 检查是否包含ASCII可打印字符
        printable_count = sum(1 for b in block if 32 <= b <= 126)
        
        if unique_values > 200 and printable_count > 50:
            # 验证已知映射
            known = {
                0xa1: ord('m'),
                0xf3: ord('o'),
                0x6b: ord('d'),
                0x31: ord('e'),
                0xb0: ord('l'),
                0x69: ord('"'),
                0x01: ord(':'),
                0x90: ord(' ')
            }
            
            matches = sum(1 for src, dst in known.items() if block[src] == dst)
            
            if matches >= 4:
                found_blocks.append((offset, matches, unique_values, printable_count))
    
    print(f"\n找到 {len(found_blocks)} 个候选块")
    
    for i, (offset, matches, unique, printable) in enumerate(found_blocks[:10]):
        print(f"\n候选 {i+1}:")
        print(f"  偏移: 0x{offset:08x}")
        print(f"  匹配已知映射: {matches}/8")
        print(f"  唯一值: {unique}/256")
        print(f"  可打印字符: {printable}")
        
        # 保存候选
        with open(f'go_candidate_{i+1}.bin', 'wb') as f:
            f.write(data[offset:offset+256])

def try_all_candidates():
    """测试所有候选映射表"""
    print("\n\n🧪 === 测试所有候选表 ===")
    
    import os
    import glob
    
    # 获取所有候选表文件
    candidates = glob.glob('*candidate*.bin') + glob.glob('*table*.bin')
    
    with open('decoded_result.bin', 'rb') as f:
        encrypted_data = f.read()
    
    for candidate_file in candidates:
        if os.path.getsize(candidate_file) == 256:
            print(f"\n测试 {candidate_file}...")
            
            with open(candidate_file, 'rb') as f:
                table = f.read()
            
            # 应用映射
            decrypted = bytearray()
            for byte in encrypted_data[:1000]:
                decrypted.append(table[byte])
            
            # 检查结果
            # 1. 可打印字符比例
            printable = sum(1 for b in decrypted if 32 <= b <= 126)
            print(f"  可打印: {printable/len(decrypted)*100:.1f}%")
            
            # 2. JSON特征
            json_features = [b'"', b':', b',', b'{', b'}']
            feature_count = sum(1 for f in json_features if f in decrypted[:100])
            
            if feature_count >= 3 and printable > 700:
                print(f"  ✅ 可能是正确的表! JSON特征: {feature_count}/5")
                
                # 显示示例
                sample = decrypted[:200]
                clean_sample = bytearray()
                for b in sample:
                    if 32 <= b <= 126:
                        clean_sample.append(b)
                    else:
                        clean_sample.append(ord('?'))
                
                print(f"  示例: {bytes(clean_sample).decode('ascii')[:100]}...")
                
                # 保存完整解密
                full_decrypted = bytearray()
                for byte in encrypted_data:
                    full_decrypted.append(table[byte])
                
                with open(f'SUCCESS_decrypted_with_{candidate_file}.txt', 'wb') as f:
                    f.write(full_decrypted)
                
                print(f"  已保存到 SUCCESS_decrypted_with_{candidate_file}.txt")

if __name__ == "__main__":
    analyze_go_symbols()
    search_custom_base64()
    
    # 尝试查找映射表
    mapping_table = analyze_byte_substitution()
    
    if mapping_table:
        print("\n\n✅ 找到映射表！正在解密...")
        
        with open('decoded_result.bin', 'rb') as f:
            encrypted = f.read()
        
        decrypted = bytearray()
        for byte in encrypted:
            decrypted.append(mapping_table[byte])
        
        with open('FINAL_DECRYPTED.json', 'wb') as f:
            f.write(decrypted)
        
        print("解密完成！查看 FINAL_DECRYPTED.json")
    else:
        search_in_go_binary_format()
        try_all_candidates()
        
        print("\n\n💡 总结:")
        print("1. 映射表可能是动态生成的")
        print("2. 检查生成的候选文件")
        print("3. 查看SUCCESS_decrypted_with_*.txt找到正确的解密")